home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
machserver
/
1.098
/
proc
/
procFamily.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-09-12
|
11KB
|
429 lines
/*
* procFamily.c --
*
* Routines to manage process families. Families are implemented using
* a hash table each entry of which points to a process family list.
* This hash table and process families in general are managed by a
* monitor lock.
*
* The only field in the proc table managed by routines in this monitor
* is the familyID field.
*
* Copyright (C) 1986 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procFamily.c,v 9.1 90/09/12 13:58:09 jhh Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include <sprite.h>
#include <proc.h>
#include <stdlib.h>
#include <status.h>
#include <sync.h>
#include <sched.h>
#include <hash.h>
static Sync_Lock familyLock;
#define LOCKPTR &familyLock
Sync_Condition familyCondition;
static Hash_Table famHashTableStruct;
static Hash_Table *famHashTable = &famHashTableStruct;
#define FAMILY_HASH_SIZE 8
/*
* A family list header.
*/
typedef struct {
List_Links famList; /* Pointer to family list. */
Boolean locked; /* TRUE => family locked. */
Sync_Condition condition; /* Condition to wait on when family
* locked. */
int userID; /* Effective userid of process that
* created the family. */
} FamilyHeader;
/*
*----------------------------------------------------------------------
*
* ProcFamilyHashInit --
*
* Initialize the family id hash table and the family lock.
*
* Results:
* None.
*
* Side effects:
* Family id hash table initialized.
*
*----------------------------------------------------------------------
*/
void
ProcFamilyHashInit()
{
Sync_LockInitDynamic(&familyLock, "Proc:familyLock");
Hash_Init(famHashTable, FAMILY_HASH_SIZE, Hash_Size(sizeof(int)));
}
/*
*----------------------------------------------------------------------
*
* ProcFamilyInsert --
*
* Insert the process into the given family.
*
* Results:
* PROC_UID_MISMATCH if effective userid of process does not match
* userid of family. SUCCESS otherwise.
*
* Side effects:
* Process inserted into family list. If family doesn't exist then
* the family is created with the userid of the given process.
*
*----------------------------------------------------------------------
*/
ENTRY ReturnStatus
ProcFamilyInsert(procPtr, familyID)
Proc_ControlBlock *procPtr;
int familyID;
{
register Hash_Entry *hashEntryPtr;
register FamilyHeader *famHdrPtr;
LOCK_MONITOR;
if (familyID == PROC_NO_FAMILY) {
UNLOCK_MONITOR;
return(SUCCESS);
}
again:
hashEntryPtr = Hash_Find(famHashTable, (Address) familyID);
famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
if (famHdrPtr == (FamilyHeader *) NIL) {
famHdrPtr = (FamilyHeader *) malloc(sizeof(FamilyHeader));
List_Init(&famHdrPtr->famList);
Hash_SetValue(hashEntryPtr, famHdrPtr);
famHdrPtr->locked = FALSE;
famHdrPtr->userID = procPtr->effectiveUserID;
} else {
if (famHdrPtr->locked) {
(void) Sync_Wait(&famHdrPtr->condition, FALSE);
goto again;
}
#ifdef CHECK_PROT
if (famHdrPtr->userID != procPtr->effectiveUserID &&
procPtr->effectiveUserID != PROC_SUPER_USER_ID) {
printf("Uid-mismatch: pid %x puid %d fid %x fuid %d\n",
procPtr->processID, procPtr->effectiveUserID,
familyID, famHdrPtr->userID);
UNLOCK_MONITOR;
return(PROC_UID_MISMATCH);
}
#endif /* */
}
List_Insert((List_Links *) &(procPtr->familyElement),
LIST_ATFRONT(&famHdrPtr->famList));
UNLOCK_MONITOR;
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* ProcFamilyRemove --
*
* Remove the process from the given family list.
*
* Results:
* None.
*
* Side effects:
* Process removed from its family list. If process isn't in a family
* then nothing happens.
*
*----------------------------------------------------------------------
*/
ENTRY void
ProcFamilyRemove(procPtr)
Proc_ControlBlock *procPtr;
{
register Hash_Entry *hashEntryPtr;
register FamilyHeader *famHdrPtr;
LOCK_MONITOR;
if (procPtr->familyID == PROC_NO_FAMILY) {
UNLOCK_MONITOR;
return;
}
hashEntryPtr = Hash_LookOnly(famHashTable, (Address) procPtr->familyID);
if (hashEntryPtr == (Hash_Entry *) NIL) {
panic("ProcFamilyRemove: Family not in hash table\n");
}
famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
while (famHdrPtr->locked) {
(void) Sync_Wait(&famHdrPtr->condition, FALSE);
}
List_Remove((List_Links *) &(procPtr->familyElement));
if (List_IsEmpty(&famHdrPtr->famList)) {
free((Address) famHdrPtr);
Hash_Delete(famHashTable, hashEntryPtr);
}
UNLOCK_MONITOR;
}
/*
*----------------------------------------------------------------------
*
* Proc_LockFamily --
*
* Prevent the given family from being modified.
*
* Results:
* PROC_INVALID_FAMILYID - The pid argument was illegal.
* PROC_UID_MISMATCH - The callers uid doesn't match the uid of the
* family.
*
* Side effects:
* Process family lock flag set.
*
*----------------------------------------------------------------------
*/
ENTRY ReturnStatus
Proc_LockFamily(familyID, familyListPtr, userIDPtr)
int familyID; /* Family to lock. */
List_Links **familyListPtr; /* Where to return pointer to family
* list. */
int *userIDPtr; /* Place to return the user id of the
* family. */
{
register Hash_Entry *hashEntryPtr;
register FamilyHeader *famHdrPtr;
LOCK_MONITOR;
again:
hashEntryPtr = Hash_LookOnly(famHashTable, (Address) familyID);
if (hashEntryPtr == (Hash_Entry *) NIL) {
UNLOCK_MONITOR;
return(PROC_INVALID_FAMILY_ID);
}
famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
if (famHdrPtr->locked) {
/*
* The family is locked so wait for it to become unlocked. When
* wake up start over because the family could have been deleted while
* we were sleeping.
*/
(void) Sync_Wait(&famHdrPtr->condition, FALSE);
goto again;
}
famHdrPtr->locked = TRUE;
*familyListPtr = &(famHdrPtr->famList);
*userIDPtr = famHdrPtr->userID;
UNLOCK_MONITOR;
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* Proc_UnlockFamily --
*
* Allow the family to be modified.
*
* Results:
* None.
*
* Side effects:
* Family id header element lock bit cleared.
*
*----------------------------------------------------------------------
*/
ENTRY void
Proc_UnlockFamily(familyID)
int familyID;
{
register Hash_Entry *hashEntryPtr;
register FamilyHeader *famHdrPtr;
LOCK_MONITOR;
hashEntryPtr = Hash_LookOnly(famHashTable, (Address) familyID);
if (hashEntryPtr == (Hash_Entry *) NIL) {
panic("Proc_UnlockFamily: Family doesn't exist\n");
}
famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
if (!famHdrPtr->locked) {
panic("Proc_UnlockFamily: Family isn't locked\n");
}
famHdrPtr->locked = FALSE;
Sync_Broadcast(&famHdrPtr->condition);
UNLOCK_MONITOR;
}
/*
*----------------------------------------------------------------------
*
* Proc_GetFamilyID --
*
* Returns the ID of the head of the process family
* for the given process.
*
* Results:
* SYS_ARG_NOACCESS - the argument was not accessible.
* SYS_INVALID_ARG - the argument was was invalid.
* PROC_INVALID_PID - the pid argument was illegal.
* PROC_UID_MISMATCH - the calling process does not have permission
* to read the given process's family id.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
ReturnStatus
Proc_GetFamilyID(pid, familyIDPtr)
Proc_PID pid;
Proc_PID *familyIDPtr;
{
register Proc_ControlBlock *procPtr;
Proc_PID familyID;
if (familyIDPtr == USER_NIL) {
return(SYS_INVALID_ARG);
}
if (pid == PROC_MY_PID) {
procPtr = Proc_GetEffectiveProc();
Proc_Lock(procPtr);
} else {
/*
* Get the PCB entry for the given process.
*/
procPtr = Proc_LockPID(pid);
if (procPtr == (Proc_ControlBlock *) NIL) {
return(PROC_INVALID_PID);
}
if (!Proc_HasPermission(procPtr->effectiveUserID)) {
Proc_Unlock(procPtr);
return(PROC_UID_MISMATCH);
}
}
familyID = procPtr->familyID;
Proc_Unlock(procPtr);
if (Proc_ByteCopy(FALSE, sizeof(Proc_PID), (Address) &familyID,
(Address) familyIDPtr) != SUCCESS){
return(SYS_ARG_NOACCESS);
}
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* Proc_SetFamilyID --
*
* Changes the family ID of a process to the one specified.
*
*
* Results:
* PROC_UID_MISMATCH - The current process did not have the same
* uid as the family or the calling process
* does not have permission to set the given
* process's family id.
* PROC_INVALID_FAMILY_ID The given family ID is not a valid process ID.
*
* Side effects:
* Changes the family ID field in the Proc_ControlBlock for a process.
*
*----------------------------------------------------------------------
*/
ReturnStatus
Proc_SetFamilyID(pid, familyID)
Proc_PID pid;
Proc_PID familyID;
{
register Proc_ControlBlock *procPtr;
Proc_ControlBlock *famProcPtr;
ReturnStatus status;
/*
* Make sure that the familyID is a valid process ID. This is necessary
* to let process group signals to be sent across machines.
*/
famProcPtr = Proc_LockPID(familyID);
if (famProcPtr == (Proc_ControlBlock *) NIL) {
return(PROC_INVALID_FAMILY_ID);
}
Proc_Unlock(famProcPtr);
if (pid == PROC_MY_PID) {
procPtr = Proc_GetEffectiveProc();
Proc_Lock(procPtr);
} else {
/*
* Get the PCB entry for the given process.
*/
procPtr = Proc_LockPID(pid);
if (procPtr == (Proc_ControlBlock *) NIL) {
return(PROC_INVALID_PID);
}
if (!Proc_HasPermission(procPtr->effectiveUserID)) {
Proc_Unlock(procPtr);
return(PROC_UID_MISMATCH);
}
}
ProcFamilyRemove(procPtr);
status = ProcFamilyInsert(procPtr, (int) familyID);
if (status == SUCCESS) {
procPtr->familyID = familyID;
} else {
procPtr->familyID = PROC_NO_FAMILY;
}
if (procPtr->state == PROC_MIGRATED) {
status = Proc_MigUpdateInfo(procPtr);
}
Proc_Unlock(procPtr);
return(status);
}